package com.handinfo.engine;

import java.io.DataInputStream;
import java.io.IOException;
import java.util.Vector;

import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;

//#if lucency == "YES"
import com.handinfo.engine.resource.ObjectAdapter;
import com.handinfo.engine.resource.ResHead;
import com.handinfo.engine.resource.Resource;
import com.handinfo.engine.resource.ResourceManager;
import com.handinfo.engine.resource.Serializeable;
import com.handinfo.game.AbstractGameActor;
import com.handinfo.game.ActorNPC;
import com.handinfo.game.ActorRole;
import com.handinfo.uimenu.UIListener;
import com.handinfo.uimenu.UIManager;
import com.handinfo.uimenu.UIMessageBox;
import com.handinfo.uimenu.UIWindowFactory;
import com.handinfo.uimenu.UiInteractMenu;
import com.handinfo.uimenu.window.UIAnnouncement;
import com.handinfo.util.ArrayList;
import com.handinfo.util.Tools;
import com.handinfo.util.UIUtil;
//import com.nokia.mid.ui.DirectGraphics;
//import com.nokia.mid.ui.DirectUtils;
//#else
//#endif
import com.test.touch.GameTouchManager;

/**
 * 
 * @author Xia Mingwei
 * @version 1.0
 */
public abstract class AbstractGameScene extends Serializeable {

    protected Image m_buffer = null;
    protected Graphics m_g;
    //#if lucency == "YES"
//	protected DirectGraphics m_dg;
	//#else
    //#endif
    public boolean m_isRepaintOnce = false;//场景是否重绘一次
    public boolean m_isPainting = true; //场景是否需要绘制
    public String m_name;
    public String m_id;
    public String[] m_texts; // 场景中的文字信息
    public AbstractGameScreen m_screen;
    public final byte PLAERS_NUM = 8;//设置显示优先级低时的同屏角色数

    public AbstractGameScene() {
        m_screen = GameManager.getInstance().m_screen;
        m_buffer = Image.createImage(AbstractGameScreen.SCREEN_WIDTH, AbstractGameScreen.SCREEN_HEIGHT);
        m_g = m_buffer.getGraphics();
        //#if lucency == "YES"
//		m_dg = DirectUtils.getDirectGraphics(m_g);
        //#endif
    }
    // //////////////////////////////////////////////////////////////////////////
    // /// 背景相关
    public Background m_bg; // 场景的背景
    public int m_bgWidth = Integer.MAX_VALUE; // 背景宽度（像素）
    public int m_bgHeight = Integer.MAX_VALUE; // 背景高度（像素）
    // /// 背景相关
    // //////////////////////////////////////////////////////////////////////////
    // //////////////////////////////////////////////////////////////////////////
    // /// ActorClass
    public Actor[] m_actorClasses; // 场景中非角色的ActorClass集合
    public ResHead[] m_actorClasses_resHead;
    // /// ActorClass
    // //////////////////////////////////////////////////////////////////////////
    // //////////////////////////////////////////////////////////////////////////
    // /// Actor
    public int m_actorMovableLayer;
    public byte[] m_actorLayers; // 元件层
    // public Actor[] m_static_actors; //场景数据中的Actor集合(装饰物)
    public ArrayList m_static_actors = new ArrayList();
    public Vector m_dynamic_actors = new Vector(100, 20); // 服务器发送的Actor集合（角色，矿点，掉落物,
    // 动态生成的npc和怪物等）
    public ArrayList m_activeList = new ArrayList(); // 活跃Actor集合（包括场景数据中的Actor和服务器发送的Actor）
    public ArrayList m_drawList = new ArrayList(); // 绘制Actor集合（包括场景数据中的Actor和服务器发送的Actor）

    // public static final int SPEED = 6 << Actor.ACTOR_FRACTION_BIT;
    public void addDynamicActor(Actor actor) {
        if (actor.m_anims != null && actor.m_anims.length > 0) {
            if (actor instanceof ActorRole) {
                actor.m_anim = actor.m_anims[1];
            } else {
                actor.m_anim = actor.m_anims[0];
            }
        }
        actor.m_enabled = true;
        actor.m_visible = true;
        actor.m_scene = this;
        actor.m_layer = this.m_actorMovableLayer;
        if (actor instanceof ActorNPC) {
            ActorNPC npc = (ActorNPC) actor;
            if (npc.m_type == ActorNPC.ACTOR_TYPE_GATE) {
                actor.m_layer -= 1;
                if (actor.m_layer < 0) {
                    actor.m_layer = 0;
                }
            }
        }
        actor.m_resource = GameManager.getInstance().m_resource_scene;
        m_dynamic_actors.addElement(actor);
    }

    public abstract Actor getActorById(int type, long id);

    public abstract Actor removeActorById(int type, long id);
    public static byte[] m_test = new byte[0];

    public void draw(Graphics g) {
        int startLayer = 0;
        int endLayer = 0;
        if (m_actorLayers.length == 0) {
            if (m_bg != null) {
                g.setColor(m_bg.m_color);
                g.fillRect(0, 0, m_cameraW, m_cameraH);
                if (m_bg.m_isUseBuffer) {
                    m_bg.drawBuffer(g, 0, m_bg.m_layerCount - 1);
                } else {
                    m_bg.draw(g, 0, m_bg.m_layerCount - 1);
                }
            }
            drawActor(g, 0);
        } else {
            for (int i = 0; i < m_actorLayers.length; i++) {
                endLayer = m_actorLayers[i];
                if (m_bg != null && endLayer >= startLayer) {
                    if (i == 0) {
                        g.setColor(m_bg.m_color);
                        g.fillRect(0, 0, m_cameraW, m_cameraH);
                    }
                    if (m_bg.m_isUseBuffer && i == 0) {
                        m_bg.drawBuffer(g, startLayer, endLayer);
                    } else {
                        m_bg.draw(g, startLayer, endLayer);
                    }
                }
                drawActor(g, i);
                startLayer = endLayer + 1;
            }
        }
        drawEffect(g);
    }

    /**
     * 绘制指定层的元件
     * 
     * @param g
     * @param layerIndex
     */
    public void drawActor(Graphics g, int layerIndex) {
        Actor a;
        int i;
        for (i = 0; i < m_drawList.size(); i++) {
            a = (Actor) m_drawList.elementAt(i);
            if (a != null && a.m_layer == layerIndex) {
                a.draw(g, m_cameraX, m_cameraY);
//				a.nextFrame();
            }
        }
    }

    /**
     * 更新m_activeList和m_drawList
     */
    public void updateActorList() {
        // 得到处于活动范围内的元件集合，绘制集合将在此集合中产生
        // m_activeCount = 0;
        m_activeList.removeAllElements();
        Actor a;
        if (m_static_actors != null) {
            for (int i = 0; i < m_static_actors.size(); i++) {
                a = (Actor) m_static_actors.elementAt(i);
                if (a == null) {
                    continue;
                }
                if (a.m_needDraw && a.m_enabled) {
                    m_activeList.addElement(a);
                }
            }
        }
        if (m_dynamic_actors != null) {
            for (int i = 0; i < m_dynamic_actors.size(); i++) {
                a = (Actor) m_dynamic_actors.elementAt(i);
                if (a == null) {
                    continue;
                }
                if (a.m_needDraw && a.m_enabled) {
                    m_activeList.addElement(a);
                }
            }
        }

        // 得到需要绘制在屏幕上的元件集合
        m_drawList.removeAllElements();
        int insertPos;
//		byte item = 1;//所有优先级人员数 至少为1 玩家自己
//		Vector team = GameManager.getInstance().m_role.m_roleTeam;
        AbstractGameActor target = GameManager.getInstance().m_role.m_targetActor;
//		if (target != null) {
//			item++;
//		}
//		if (team != null) {
//			int size = team.size();
//			if (size > 1) {
//				item += (size - 1);
//				for (int i = 0; i < size; i++) {
//					Actor b = (Actor) team.elementAt(i);
//					if (!b.m_needDraw || !b.m_visible) {
//						item--;
//					}
//				}
//				if (target != null && team.contains(target)) {
//					item--;
//				}
//			}
//		}
//		byte Maxother = (byte)(PLAERS_NUM - item);//可以任意添加的数量
        for (int i = 0; i < m_activeList.size(); i++) {
            a = (Actor) m_activeList.elementAt(i);
            // 元件不显示则跳过
            if (!a.m_needDraw || !a.m_visible) {
                continue;
            }
            insertPos = 0;
            if (a instanceof ActorRole) {
                ActorRole r = (ActorRole) a;
                r.m_viewpriority = setViewPriority(r, containRole(r.m_gameID), teamContainRole(r.m_gameID), (r == target));
            }
            while (insertPos < m_drawList.size() && ((Actor) m_drawList.elementAt(insertPos)).m_posY < a.m_posY) {
                insertPos++;
            }
            m_drawList.insertElementAt(a, insertPos);
        }
    }

    /**
     * 根据系统显示设置角色显示等级
     * */
    public byte setViewPriority(ActorRole role, boolean isOwn, boolean isTeam, boolean isTarget) {
        if (role == null) {
            return 0;
        }
        switch (GameManager.s_system_infos[GameManager.SET_DIS_PLAYERS]) {
            case 0://显示等级最低  只有自己和目标完全显示
                if (isOwn || isTarget) {
                    return 2;
                }
                return 0;
            case 1://显示等级中 只有自己和目标和队友完全显示 其他所有人为影子和名字
                if (isOwn || isTarget || isTeam) {
                    return 2;
                }
                return 1;
            case 2://显示等级最高 全部显示
                return 2;
            default:
                return role.m_viewpriority;
        }
    }

    /**
     * 根据ID判断是否是队伍中成员
     * @param long gameId
     * @return boolean
     * */
    public boolean teamContainRole(long gameId) {
        Vector team = GameManager.getInstance().m_role.m_roleTeam;
        if (team == null) {
            return false;
        }
        ActorRole role;
        for (int i = 0; i < team.size(); i++) {
            role = (ActorRole) team.elementAt(i);
            if (role.m_gameID == gameId) {
                return true;
            }
        }
        return false;
    }

    /**
     * 根据ID是否是玩家自己
     * @param long gameId
     * @return boolean
     * */
    public boolean containRole(long gameId) {
        if (GameManager.getInstance().m_role.m_gameID == gameId) {
            return true;
        }
        return false;
    }
    private int currTimes = 0;
    private final int maxTimes = 100;

    /**
     * 逻辑
     */
    public void updateLogic() {
        keyLogic();
        int i = 0;
        Actor a;
        for (i = m_static_actors.size() - 1; i >= 0; i--) {
            a = (Actor) m_static_actors.elementAt(i);
            if (a != null && a.m_enabled) {
                a.updatePos();
                a.logic();
                a.nextFrame();
            }
        }
        // 更新动态Actors位置
        for (i = m_dynamic_actors.size() - 1; i >= 0; i--) {
            a = (Actor) m_dynamic_actors.elementAt(i);
            if (a != null && a.m_enabled) {
                a.updatePos();
                a.logic();
                a.nextFrame();
            }
        }
        //定时提交缺省资源
//        if (currTimes < maxTimes) {
//            currTimes++;
//        } else {
//            ResourceManager.getInstance().requestResources();
//            currTimes = 0;
//        }
    }

    /**
     * 场景帧处理，用于一些动作执行中使用，仅进行场景中元件和背景帧的处理而不进行逻辑处理
     */
    public void updateFrame() {
        // 如果背景不为空则执行背景逻辑
        if (m_bg != null) {
            m_bg.tick();
        }
        // 遍历场景中所有的元件，执行元件逻辑
        Actor a;
        // 更新静态Actors位置
        for (int i = m_static_actors.size() - 1; i >= 0; i--) {
            a = (Actor) m_static_actors.elementAt(i);
            if (a != null && a.m_enabled) {
                a.updatePos();
            }
        }
    }
    // /// Actor
    // //////////////////////////////////////////////////////////////////////////
    // /////////////////////////////////////////////////////////////////
    // // 脚本相关
    public AbstractGameScript m_script; // 脚本对象

    public void setEventActorInfo(int actorClass, int actorId, int actorAction) {
        m_script.setEventActorInfo(actorClass, actorId, actorAction);
    }

    public void setCollideActorInfo(int actorClass, int actorId, int actorAction) {
        m_script.setCollideActorInfo(actorClass, actorId, actorAction);
    }

    public void setActiveActorInfo(int actorClass, int actorId, int actorAction) {
        m_script.setActiveActorInfo(actorClass, actorId, actorAction);
    }

    public void fireEvent(int id) {
        m_script.fireEvent(id);
    }
    /**
     * 过场动画遮幅高度
     */
    public int m_trailerModeHeight = 0;

    /**
     * 绘制过场动画模式 过场动画模式就是类似电影画面，在屏幕的上下方各画一段黑色遮幅
     * 
     * @param g
     */
    public void drawTrailerMode(Graphics g) {
        if (m_trailerModeHeight <= 0) {
            return;
        }
        g.setColor(0x000000);
        g.fillRect(0, 0, m_cameraW, m_trailerModeHeight);
        g.fillRect(0, m_cameraH - m_trailerModeHeight, m_cameraW,
                m_trailerModeHeight);
    }

    // //以下是action的实现
    /**
     * 设置场景中元件的属性
     * 
     * @param actor
     * 元件
     * @param actionId
     * 动作
     * @param x
     * X坐标
     * @param y
     * Y坐标
     */
    public void setActor(Actor actor, int actionId, int x, int y) {
        if (actor == null) {
            return;
        }
        actor.m_enabled = true;
        actor.m_visible = true;
        actor.m_needDraw = true;
        actor.setAction(actionId, true);
        actor.m_prevPosX = actor.m_posX;
        actor.m_prevPosY = actor.m_posY;
        actor.m_posX = x;
        actor.m_posY = y;
    }

    /**
     * 移动镜头到指定坐标
     * @param vx
     * @param vy
     * @param speed
     */
    public void moveCamera(int vx, int vy, int speed) {
        boolean atPos = false;
        setFocusActor(null);
        vx -= m_cameraW / 2;
        vy -= m_cameraH / 2;
        while (!atPos) {
            if (m_destCameraX < vx) {
                m_destCameraX += speed;
                if (m_destCameraX > vx) {
                    m_destCameraX = vx;
                }
            }
            if (m_destCameraX > vx) {
                m_destCameraX -= speed;
                if (m_destCameraX < vx) {
                    m_destCameraX = vx;
                }
            }
            if (m_destCameraY < vy) {
                m_destCameraY += speed;
                if (m_destCameraY > vy) {
                    m_destCameraY = vy;
                }
            }
            if (m_destCameraY > vy) {
                m_destCameraY -= (speed);
                if (m_destCameraY < vy) {
                    m_destCameraY = vy;
                }
            }
            if (m_destCameraX == vx && m_destCameraY == vy) {
                atPos = true;
            }

            updateFrame();
            updateActorList();
            draw(m_screen.getGraphics());
            drawTrailerMode(m_screen.getGraphics());

            GameManager.getInstance().keepConnectionAlive();

            m_screen.flush();
            GameManager.waitAnyTime(80);
        }
    }

    /**
     * 播放元件动作
     * 
     * @param actor
     * Actor
     */
    public void playActorAction(Actor actor) {
        while (!actor.m_actionOver) {
            updateTrailer();
            m_screen.flush();
            GameManager.waitAnyTime(80);
        }
    }

    /**
     * 显示对话框
     * 
     * @param faceId
     * int 头像ID
     * @param facial
     * int 表情
     * @param name
     * String 名字
     * @param text
     * String 内容
     */
    public void showDialog(int faceId, int faceActionId, String name,
            String text) {
        UIUtil.showDialog(m_screen.getGraphics(), name, text, 100, null, 0,
                AbstractGameScreen.SCREEN_HEIGHT - UIUtil.DLG_HEIGHT,
                AbstractGameScreen.SCREEN_WIDTH, UIUtil.DLG_HEIGHT, false);
    }

    /**
     * 绘制交互对话框
     * @param content
     */
    public void showInteractDialog(String content) {
        UiInteractMenu dialog = (UiInteractMenu) UIWindowFactory.createWindow(UIWindowFactory.WINDOW_INTERACT);
        updateTrailer();
        dialog.paint(m_screen.getGraphics());
        m_screen.flush();
        GameManager.waitAnyKey();

//		boolean showing = true;
//		long tick = 0;
//		while(showing) {
//			tick = System.currentTimeMillis() + GameManager.FRAME_INTERVAL;
//			AbstractGameScreen.updateKeyBegin();
//			updateTrailer();
//			dialog.paint(m_screen.getGraphics());
//			
//			if (AbstractGameScreen.anyKeyPressed()) {
//				showing = false;
//			}
//			AbstractGameScreen.updateKeyEnd();
//			m_screen.flush();
//			while (tick > System.currentTimeMillis()) {
//				Thread.yield();
//			}
//		}
    }

    /**
     * 刷新场景动画
     */
    public void updateTrailer() {
        updateFrame();
        updateCamera();
        updateActorList();
        draw(m_screen.getGraphics());
        drawTrailerMode(m_screen.getGraphics());

        GameManager.getInstance().keepConnectionAlive();
    }
    // // 脚本相关
    // /////////////////////////////////////////////////////////////////
    // //////////////////////////////////////////////////////////////////////////
    // // 场景效果
    public static final int EFFECT_BLACK = 0;//晴
    public static final int EFFECT_RAIN = 1;//雨
    public static final int EFFECT_RED_RAIN = 2;//红雨
    public static final int EFFECT_SNOW = 3;//雪
    public static final int EFFECT_RED_SNOW = 4; //红雪
    /**
     * 特效是否开启标记
     */
    public boolean m_effectOn = false;
    public int m_effectId = 0; // 特效ID
    public int m_effectColour; // 特效颜色

    /**
     * 绘制屏幕特效 (例如下雨，下雪等等)
     * 
     * @param g
     */
    public void drawEffect(Graphics g) {
        if (GameManager.s_system_infos[GameManager.SET_DIS_WEATHER] == 0) {
            return;
        }
		if ((m_effectId & 1 << EFFECT_RAIN) != 0 || (m_effectId & 1 << EFFECT_RED_RAIN)!= 0) { // 如果下雨特效开启
			Tools.startRain(g, m_cameraX, m_cameraY, m_cameraW, m_cameraH, 0, m_effectColour);
		}
		if ((m_effectId & 1 << EFFECT_SNOW) != 0 || (m_effectId & 1 << EFFECT_RED_SNOW) != 0) { // 如果下雪特效开启
			Tools.startSnow(g, m_cameraX, m_cameraY, m_cameraW, m_cameraH, 0, m_effectColour);
		}
    }

    /**
     * 屏幕闪屏特效
     * 
     * @param flashId
     * 特效元件ID
     * @param color
     * 闪屏颜色
     */
    public void flashScreen(int flashId, int color) {
        Graphics g = m_screen.getGraphics();
        flash(g, 3, color);
    }

    /**
     * 进入战斗的闪屏效果
     * 
     * @param g
     * Graphics
     * @param count
     * int
     * @param color
     * int
     */
    public void flash(Graphics g, int count, int color) {
        for (int i = 0; i < count; i++) {
            g.setColor(color);
            g.fillRect(0, 0, m_cameraW, m_cameraH);
            m_screen.flush();
            GameManager.waitAnyTime(50);
        }
    }

    public boolean m_isFade;
    public int m_fadeId = 0;
    
    /**
     * 屏幕渐隐渐显效果
     * 
     * @param isFadeIn
     * 是否渐显标记
     * @param fadeId
     * 效果ID
     */
    public void screenFade(boolean isFadeIn, int fadeId) {
    	//Tools.debugPrintln("isFadeIn="+isFadeIn+";fadeID="+fadeId);
        Graphics g = m_screen.getGraphics();
//        if (isFadeIn) {
//            m_effectId &= ~(1 << EFFECT_BLACK); // 去掉黑屏效果，不然场景画不出来
//        }
          if ( !isFadeIn ){
        	   return;
          }
        if (fadeId == 0) { // 半透黑屏
            final int LIMIT = 16;
            int tick = LIMIT;
            int temp = 0;
            while (tick-- > 0) {
                if (isFadeIn) {
                    draw(g);
                }
                temp = isFadeIn ? tick + 1 : LIMIT - tick;
                int colAlpha = 0xff * temp / LIMIT << 24;

                Tools.fillRect(g, 0, 0, AbstractGameScreen.SCREEN_WIDTH,
                        AbstractGameScreen.SCREEN_HEIGHT, colAlpha);

                drawTrailerMode(g);
                m_screen.flush();
                GameManager.waitAnyTime(60);
            }
        } else if (fadeId == 1) { // 爆菊
            final int LIMIT = 20;
            int tick = LIMIT;
            int temp = 0;
            int w = AbstractGameScreen.SCREEN_WIDTH / 2;
            int h = AbstractGameScreen.SCREEN_HEIGHT / 2;
            int wn = 0;
            int hn = 0;
            while (tick-- > 0) {
                if (isFadeIn) {
                    draw(g);
                }
                temp = isFadeIn ? tick + 1 : LIMIT - tick;
                wn = AbstractGameScreen.SCREEN_WIDTH / temp
                        - AbstractGameScreen.SCREEN_WIDTH / LIMIT;
                hn = AbstractGameScreen.SCREEN_HEIGHT / temp
                        - AbstractGameScreen.SCREEN_HEIGHT / LIMIT;
                g.setColor(0x000000);
                g.fillRect(0 - wn, 0 - hn, w, h);
                g.fillRect(w + wn, 0 - hn, w, h);
                g.fillRect(0 - wn, h + hn, w, h);
                g.fillRect(w + wn, h + hn, w, h);
                //
                drawTrailerMode(g);
                m_screen.flush();
                GameManager.waitAnyTime(60);
            }
        } else if (fadeId == 2) { // 双向横线
            final int LIMIT = 20;
            final int n = 20;
            int tick = LIMIT;
            int temp = 0;
            int w = AbstractGameScreen.SCREEN_WIDTH / n + 1;
            int h = AbstractGameScreen.SCREEN_HEIGHT / n + 1;
            while (tick-- > 0) {
                if (isFadeIn) {
                    draw(g);
                }
                temp = isFadeIn ? tick - 2 : LIMIT - tick;
                g.setColor(0x000000);
                for (int i = 0; i < n; i++) {
                    if (i % 2 == 0) {
                        g.fillRect(-AbstractGameScreen.SCREEN_WIDTH + temp * w,
                                h * i, AbstractGameScreen.SCREEN_WIDTH, h);
                    } else {
                        g.fillRect(AbstractGameScreen.SCREEN_WIDTH - temp * w,
                                h * i, AbstractGameScreen.SCREEN_WIDTH, h);
                    }
                }

                drawTrailerMode(g);
                m_screen.flush();
                GameManager.waitAnyTime(60);
            }
        } else if (fadeId == 3) { // 随机线
            final int LIMIT = 60;
            final int n = 40;
            int w = AbstractGameScreen.SCREEN_WIDTH / n + 1;
            int tick = LIMIT;
//			int temp = 0;
            ArrayList v = new ArrayList(n, n / 2);
            boolean[] show = new boolean[n];
            for (int i = 0; i < show.length; i++) {
                if (isFadeIn) {
                    show[i] = true;
                }
                v.addElement(new Integer(i));
            }
            while (tick-- > 0) {
                if (isFadeIn) {
                    draw(g);
                }
//				temp = isFadeIn ? tick + 1 : LIMIT - tick;
                g.setColor(0x000000);
                int ran = Tools.random(v.size() - 1);
                if (0 < ran) {
                    Integer integer = (Integer) v.elementAt(ran);
                    int d = integer.intValue();
                    show[d] = isFadeIn ? false : true;
                    v.removeElementAt(ran);
                }
                if (0 == ran) {
                    show[0] = isFadeIn ? false : true;
                }
                for (int i = 0; i < n; i++) {
                    if (show[i]) {
                        g.fillRect(i * w, 0, w,
                                AbstractGameScreen.SCREEN_HEIGHT);
                    }
                }
                //
                drawTrailerMode(g);
                m_screen.flush();
                GameManager.waitAnyTime(20);
            }
        } else if (fadeId == 4) { // 螺旋
            final int CIRCLE = 360;
            final int NUM = 8;
            final int LIMIT = CIRCLE * NUM;
            int tick = LIMIT;
            int temp = 0;
            while (tick > 0) {
                if (isFadeIn) {
                    draw(g);
                }
                temp = isFadeIn ? tick + 1 : LIMIT - tick;
                g.setColor(0x000000);
                for (int j = 0; j < NUM; j++) {
                    if (temp > CIRCLE * j) {
                        Tools.fillArc(g, 0x88000000,
                                AbstractGameScreen.SCREEN_WIDTH / 2,
                                AbstractGameScreen.SCREEN_HEIGHT / 2, 60 * j,
                                45, (360 + 45) * (temp - CIRCLE * j) / CIRCLE);
                    }
                }
                tick -= 100;
                //
                drawTrailerMode(g);
                m_screen.flush();
                GameManager.waitAnyTime(60);
            }
        } else if (fadeId == 5) { // 模糊
            final int LIMIT = 20;
            int tick = LIMIT;
            while (tick-- > 0) {
                g.setColor(0x000000);
//                 Tools.paintBlurEffect(s_canvas.getBufImage(), g, 0, 0,
//                 AbstractGameScreen.SCREEN_WIDTH,
//                 AbstractGameScreen.SCREEN_HEIGHT, 100, 10,
//                 Tools.BLUR_LEFT);
                drawTrailerMode(g);
                m_screen.flush();
                GameManager.waitAnyTime(60);
            }
        }
           m_isFade = false;
//        if (!isFadeIn) {
//            m_effectOn = true;
//            m_effectId |= (1 << EFFECT_BLACK); // 加上黑屏效果
//        }
    }
    // // 场景效果
    // //////////////////////////////////////////////////////////////////////////
    // //////////////////////////////////////////////////////////////////////////
    // //// 摄像机相关
    public int m_cameraX; // 摄像机X坐标
    public int m_cameraY; // 摄像机Y坐标
    public int m_cameraW; // 摄像机宽度
    public int m_cameraH; // 摄像机高度
    public int m_destCameraX; // 目的摄像机X坐标
    public int m_destCameraY; // 目的摄像机Y坐标
    public int m_cameraSpeed = 20; // 摄像机移动速度
    public int m_cameraLimitX = 0; // 摄像机限制区起始点X坐标
    public int m_cameraLimitW = Integer.MAX_VALUE; // 摄像机限制区结束点X坐标
    public int m_cameraLimitY = 0; // 摄像机限制区起始点Y坐标
    public int m_cameraLimitH = Integer.MAX_VALUE; // 摄像机限制区结束点Y坐标
    public boolean m_forceCamera = true; // 强制将当前摄像机坐标移动到目的摄像机
    public boolean m_smoothCamera = true; // 是否平滑移动摄像机，每帧移动距离不能超过范围
    /**
     * 摄像机元件，该元件的位置决定了当前场景的摄像机
     */
    public Actor m_focusActor;
    public Actor m_oldFocusActor; // 用来临时记录上一个摄像机元件

    /**
     * 设置摄像机元件
     * 
     * @param viewActor
     */
    public void setFocusActor(Actor viewActor) {
        this.m_focusActor = viewActor;
    }

    /**
     * 更新摄像机信息
     */
    public void updateCamera() {
        if (!m_isPainting) {
            return;
        }
        if (m_focusActor != null) {
            m_destCameraX = m_focusActor.m_posX - (m_cameraW >> 1);
            m_destCameraY = m_focusActor.m_posY - (m_cameraH >> 1);
        }
        // 调整摄像机
        if (m_cameraX < m_destCameraX) {
            m_cameraX += m_cameraSpeed;
            if (m_cameraX > m_destCameraX) {
                m_cameraX = m_destCameraX;
            }
        }
        if (m_cameraX > m_destCameraX) {
            m_cameraX -= m_cameraSpeed;
            if (m_cameraX < m_destCameraX) {
                m_cameraX = m_destCameraX;
            }
        }
        if (m_cameraY < m_destCameraY) {
            m_cameraY += m_cameraSpeed;
            if (m_cameraY > m_destCameraY) {
                m_cameraY = m_destCameraY;
            }
        }
        if (m_cameraY > m_destCameraY) {
            m_cameraY -= (m_cameraSpeed);
            if (m_cameraY < m_destCameraY) {
                m_cameraY = m_destCameraY;
            }
        }
        if (m_forceCamera || !m_smoothCamera) { // 是否强制切换摄像机
            m_cameraX = m_destCameraX;
            m_cameraY = m_destCameraY;
            m_forceCamera = false;
        }
        setCameraXY(m_cameraX, m_cameraY);
    }

    /**
     * 设置摄像机限制区域
     * 
     * @param cameraX
     * int
     * @param cameraY
     * int
     * @param cameraW
     * int
     * @param cameraH
     * int
     */
    public void setCameraLimit(int cameraX, int cameraY, int cameraW,
            int cameraH) {
        m_cameraLimitX = cameraX;
        m_cameraLimitY = cameraY;
        m_cameraLimitW = cameraW;
        m_cameraLimitH = cameraH;
    }

    /**
     * 设置场景摄像机
     * 
     * @param viewX
     * @param viewY
     */
    public void setCameraXY(int cameraX, int cameraY) {
        // 有特殊的摄像机限制
        // this.m_cameraX = Tools.limit(cameraX, m_cameraLimitX,
        // m_cameraLimitX + m_cameraLimitW - AbstractGameScreen.SCREEN_WIDTH);
        // this.m_cameraY = Tools.limit(cameraY, m_cameraLimitY,
        // m_cameraLimitY + m_cameraLimitH - AbstractGameScreen.SCREEN_HEIGHT);

        this.m_cameraX = Tools.limit(cameraX, 0, m_bgWidth
                - AbstractGameScreen.SCREEN_WIDTH);
        this.m_cameraY = Tools.limit(cameraY, 0, m_bgHeight
                - AbstractGameScreen.SCREEN_HEIGHT);
        if (m_bg != null) {
            m_bg.setCameraXY(this.m_cameraX, this.m_cameraY);
        }
    }

    public void setCameraWH(int cameraW, int cameraH) {
        m_cameraW = cameraW;
        m_cameraH = cameraH;
    }

    // //// 摄像机相关
    // //////////////////////////////////////////////////////////////////////////
    /**
     * 按键逻辑
     */
    public abstract void keyLogic();
    public int m_frameCount = 0;
    public boolean m_isRunning = true;
    public static boolean SHOWTIME = true;
    private static long s_fps_start = 0;
    private static long s_fps_end = 0;
    public static int s_fps = 0;
    public static long s_flushTime = 0;
    public static int s_repaintTime = 0;
    public static long s_tickCount = 0;

    public void run() {
        AbstractGameScreen screen = GameManager.getInstance().getScreen();
        Graphics g = m_g;
//		Graphics g = screen.getGraphics();
        long tick = 0;
//		init();
        m_isRunning = true;
        while (m_isRunning) {
            tick = System.currentTimeMillis() + GameManager.FRAME_INTERVAL;
            if (Tools.DEBUG) {
                s_fps_start = System.currentTimeMillis();
                s_repaintTime = (int) (s_fps_start + GameManager.FRAME_INTERVAL - tick);
            }

            AbstractGameScreen.updateKeyBegin();

            if (!m_script.m_trailerEnd && m_script.m_curTrailerId != -1) {
                m_script.runTrailer(true, m_script.m_curTrailerId);
            }
            if (GameManager.getInstance().m_game_message != null) {
                if (GameManager.getInstance().m_game_message.networkTimeLogic()) {
                    Tools.debugPrintln("GameScene network exception!");
                    GameManager.getInstance().dealForConnectionException();
                }
            }
            updateLogic();
            updateCamera();
            updateActorList();
            draw(g);
            //TODO zheli
            screenFade(m_isFade, m_fadeId);
            GameManager.getInstance().runMessage();
            GameManager.getInstance().runSysMessage();
            if (GameManager.getInstance().m_game_message != null) {
                GameManager.getInstance().m_game_message.drawNetworkTime(g);
            }
            GameManager.getInstance().keepConnectionAlive();
            AbstractGameScreen.updateKeyEnd();
            screen.flush();
            if (Tools.DEBUG) {
                s_flushTime = System.currentTimeMillis() - s_fps_start;
                if ((s_tickCount & 15) == 0) {
                    if (s_fps_end == 0) {
                        s_fps_end = s_flushTime + s_fps_start;
                    }
                    int frame16time = (int) (s_flushTime + s_fps_start - s_fps_end);
                    if (frame16time != 0) {
                        s_fps = 16000 / frame16time;
                    }
                    s_fps_end = s_flushTime + s_fps_start;
                }
            }
            while (tick > System.currentTimeMillis()) {
                Thread.yield();
            }
            m_frameCount++;
            s_tickCount++;
        }
        UIManager.getInstance().removeAllWindows();
    }

    public void init() {
    	GameTouchManager.clearStaticRects();
        m_isPainting = true;
        m_isRepaintOnce = false;
        m_cameraW = AbstractGameScreen.SCREEN_WIDTH;
        m_cameraH = AbstractGameScreen.SCREEN_HEIGHT;
        m_bgWidth = m_bg.m_tileW * m_bg.m_columns;
        m_bgHeight = m_bg.m_tileH * m_bg.m_rows;
        m_cameraLimitX = 0;
        m_cameraLimitY = 0;
        m_cameraLimitW = Math.max(0, m_bgWidth - m_cameraW);
        m_cameraLimitH = Math.max(0, m_bgHeight - m_cameraH);
        boolean useBuffer = true;
        int firstActorLayer = 0;
        if (m_actorLayers.length > 0) {
            firstActorLayer = m_actorLayers[0];
        } else {
            firstActorLayer = m_bg.m_layerCount - 1;
        }
        if (m_bg.m_layers != null) {
            for (int j = 0; j <= firstActorLayer; j++) {
                if (m_bg.m_layers[j] != null
                        && m_bg.m_layers[j].m_type != Layer.TYPE_TILEDLAYER
                        && m_bg.m_layers[j].m_type != Layer.TYPE_PHYSICALLAYER) {
                    useBuffer = false;
                    break;
                }
            }
            m_bg.m_isUseBuffer = useBuffer;
        }

        m_bg.setCameraWH(m_cameraW, m_cameraH);
        m_bg.initResource();
    }

    public void loadActorClasses(Resource res) throws IOException {
        m_actorClasses = new Actor[m_refsResHead.length - 1];
        m_actorClasses_resHead = new ResHead[m_refsResHead.length - 1];
        for (int i = 0; i < m_actorClasses.length; i++) {
            m_actorClasses[i] = (Actor) (ResourceManager.getInstance().loadResource(res, m_refsResHead[i + 1]));
            m_actorClasses[i].m_scene = this;
            m_actorClasses[i].m_visible = false;
            m_actorClasses[i].m_enabled = false;
            m_actorClasses_resHead[i] = m_refsResHead[i + 1];
        }
    }
    
    public void loadActorClasses(Resource res, DataInputStream dis) throws IOException {
    	int size = dis.readShort();
    	m_actorClasses = new Actor[size];
    	m_actorClasses_resHead = new ResHead[size];
    	for (int i = 0; i < m_actorClasses.length; i++) {
    		m_actorClasses_resHead[i] = new ResHead(dis.readByte(), ObjectAdapter.DIR_AC.concat(dis.readUTF()).concat(
					ObjectAdapter.EXTENSION_AC), 1);
    		switch(m_actorClasses_resHead[i].m_type) {
    			case ObjectAdapter.RESOURCE_TYPE_ACTOR:
    				m_actorClasses[i] = new Actor(this);
    				break;
    			case ObjectAdapter.RESOURCE_TYPE_NPC:
    				m_actorClasses[i] = new ActorNPC();
    				break;
    			default:
    				break;
    		}
    		if (m_actorClasses[i] != null) {
    			m_actorClasses[i].read(res, dis);
    			res.put(m_actorClasses_resHead[i], m_actorClasses[i]);
    		}
    	}
    }

    public void loadBackground(Resource res) throws IOException {
        m_bg = (Background) (ResourceManager.getInstance().loadResource(res,
                m_refsResHead[0]));
    }

    public void read(Resource res, DataInputStream dis) throws IOException {
        readHeader(res, dis);
        loadActorClasses(res, dis);
        loadBackground(res);
        // 载入名字
        m_name = dis.readUTF();
        Tools.debugPrintln("ags read name : " + m_name);
        // 活动层
        m_actorMovableLayer = dis.readByte();
        // 载入元件层数据
        int count = dis.readByte(); // 元件层数量
        m_actorLayers = new byte[count];
        for (int i = 0; i < count; i++) {
            m_actorLayers[i] = dis.readByte();
        }
        // 载入场景中字符串
        count = dis.readShort();
        m_texts = new String[count];
        for (int i = 0; i < count; i++) {
            m_texts[i] = dis.readUTF();
        }
        // 载入Actor信息
        count = dis.readShort();
        Actor actorClass;
        for (int i = 0; i < count; i++) {
            int inx = dis.readShort();
            actorClass = m_actorClasses[inx];
            Actor actorInstance = null;
            if (actorClass != null) {
                switch (m_actorClasses_resHead[inx].m_type) {
                    case ObjectAdapter.RESOURCE_TYPE_ACTOR:
                        actorInstance = actorClass.clone();
                        break;
                    default:
                    	//空出该索引位，因为脚本动画是以索引为依据取Actor
                        dis.skip(10);
                        m_static_actors.addElement(null);
                        continue;
                }
            } else {
                switch (m_actorClasses_resHead[inx].m_type) {
                    case ObjectAdapter.RESOURCE_TYPE_ACTOR:
                        actorInstance = new Actor();
                        break;
                    default:
                    	//空出该索引位，因为脚本动画是以索引为依据取Actor
                        dis.skip(10);
                        m_static_actors.addElement(null);
                        continue;
                }
            }
            m_static_actors.addElement(actorInstance);
            actorInstance.m_resHead = m_actorClasses_resHead[inx];
            actorInstance.m_flag = dis.readInt();
            actorInstance.m_flipX = (actorInstance.m_flag & 0x01) != 0;
            actorInstance.m_flipY = (actorInstance.m_flag & 0x02) != 0;
            actorInstance.m_enabled = true;
            actorInstance.m_visible = true;
            // actorInstance.m_enabled = (actorInstance.m_flag & 0x04) != 0;
            // actorInstance.m_visible = (actorInstance.m_flag & 0x08) != 0;
            int action = dis.readByte();
            if (action < 0) {
                action += 256;
            }
            actorInstance.setAction(action, true, true);
            actorInstance.m_layer = dis.readByte();
            actorInstance.m_posX = dis.readShort();
            actorInstance.m_posY = dis.readShort();
            actorInstance.m_id = (short) i;
        }
        // 载入场景中事件和脚本相关数据
        m_script.loadTrailerData(dis);

        checkLoadFinished();
    }

    public void checkLoadFinished() {
        if (m_bg == null) {
            m_loadFinished = false;
            return;
        }
        if (m_actorClasses == null) {
            m_loadFinished = false;
            return;
        }
        for (int i = 0; i < m_actorClasses.length; i++) {
            if (m_actorClasses[i] == null) {
                m_loadFinished = false;
                return;
            }
        }
        m_loadFinished = true;
    }

    public void updateComponent(ResHead head, Serializeable component) {
        if (m_loadFinished) {
            return;
        }
        if (head.m_type != ObjectAdapter.RESOURCE_TYPE_BG
                && head.m_type != ObjectAdapter.RESOURCE_TYPE_ACTOR) {
            return;
        }
        if (m_refsResHead == null || m_refsResHead.length == 0) {
            return;
        }
        for (int i = 0; i < m_refsResHead.length; i++) {
            if (m_refsResHead[i].equals(head)) {
                if (i == 0) {
                    m_bg = (Background) component;
                } else {
                    m_actorClasses[i - 1] = (Actor) component;
                    Actor actor;
                    synchronized (m_static_actors) {
                        for (int ii = 0; ii < m_static_actors.size(); ii++) {
                            actor = (Actor) m_static_actors.elementAt(ii);
                            if (actor == null) {
                                continue;
                            }
                            if (actor.m_resHead.equals(m_actorClasses[i - 1].m_resHead)) {
                                actor.copy(m_actorClasses[i - 1]);
                            }
                        }
                    }
                    for (int ii = 0; ii < m_dynamic_actors.size(); ii++) {
                        actor = (Actor) m_dynamic_actors.elementAt(ii);
                        if (actor == null) {
                            continue;
                        }
                        if (actor.m_resHead.equals(m_actorClasses[i - 1].m_resHead)) {
                            actor.copy(m_actorClasses[i - 1]);
                        }
                    }
                }
                checkLoadFinished();
            }
        }
    }

    public boolean isContainHeader(ResHead head) {
        if (head.m_type != ObjectAdapter.RESOURCE_TYPE_BG
                && head.m_type != ObjectAdapter.RESOURCE_TYPE_ACTOR) {
            return false;
        }
        if (m_refsResHead == null || m_refsResHead.length == 0) {
            return false;
        }
        for (int i = 0; i < m_refsResHead.length; i++) {
            if (m_refsResHead[i].equals(head)) {
                return true;
            }
        }
        return false;
    }

    public synchronized void dispose() {
        disposeHeader();
        if (m_actorClasses != null) {
            for (int i = 0; i < m_actorClasses.length; i++) {
                if (m_actorClasses[i] != null) {
                    m_actorClasses[i] = null;
                }
            }
            m_actorClasses = null;
        }
//		m_actorClasses_type = null;
        m_actorLayers = null;
        m_bg = null;
        if (m_dynamic_actors != null) {
            Actor actor;
            for (int i = 0; i < m_dynamic_actors.size(); i++) {
                actor = (Actor) m_dynamic_actors.elementAt(i);
                if (actor != null) {
                    actor.dispose();
                }
            }
            m_dynamic_actors.removeAllElements();
            m_dynamic_actors = null;
        }
        if (m_static_actors != null) {
            Actor actor;
            for (int i = 0; i < m_static_actors.size(); i++) {
                actor = (Actor) m_static_actors.elementAt(i);
                if (actor != null) {
                    actor.dispose();
                }
            }
            m_static_actors.removeAllElements();
            m_static_actors = null;
        }
        m_focusActor = null;
        //#if lucency == "YES"
//         m_dg = null;
        //#endif
        m_g = null;
        m_buffer = null;
    }

    /**
     * 处理网络消息
     * 
     * @param type
     * @param body
     * @return
     */
    public abstract boolean recvMessage(int type, byte[] body);
    
	/**
	 * 询问退出游戏
	 */
	public void exitGame()
	{
		final UIMessageBox mbox = (UIMessageBox) UIManager.getInstance().createWindow(UIWindowFactory.WINDOW_MESSAGEBOX);
		GameManager.s_isControlledByUi = true;
		mbox.setMessage("是否确定要退出游戏?");
		mbox.addListener(new UIListener() {
			public void actionPerformed() {
				if (AbstractGameScreen.haveKeyPressed(AbstractGameScreen.GK_LEFT_SOFT)
						|| AbstractGameScreen.haveKeyPressed(AbstractGameScreen.GK_A)) {
					m_isRunning = false;
					GameManager.s_isRunning = false;
					GameMIDlet.s_isJumpWap = true;
					UIManager.getInstance().removeWindow(mbox);
					GameManager.s_isControlledByUi = false;
				}
				else if (AbstractGameScreen.haveKeyPressed(AbstractGameScreen.GK_RIGHT_SOFT)) {
					UIManager.getInstance().removeWindow(mbox);
					GameManager.s_isControlledByUi = false;
				}
			}
		});
	}
}
